package util

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	cryx509 "crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"errors"
	"fmt"
	"github.com/tjfoc/gmsm/sm3"
	"github.com/tjfoc/gmsm/x509"
	"go.uber.org/zap"
	"log"
	"os"
)

func Sm2Sign(priKey string, msg []byte) ([]byte, error) {
	privateKey, err := x509.ReadPrivateKeyFromPem([]byte(priKey), nil)
	if err != nil {
		return nil, err
	}
	return privateKey.Sign(rand.Reader, msg, nil)
}
func Sm2Verify(pbKey string, msg []byte, sign []byte) bool {
	sm2PubKey, err := x509.ReadPublicKeyFromPem([]byte(pbKey))
	if err != nil {
		zap.L().Error("sm2 verify err", zap.Error(err))
		return false
	}

	return sm2PubKey.Verify(msg, sign)
}

func SM2Encrypt(publicKeyPath string, msg []byte) []byte {
	file, err := os.Open(publicKeyPath)
	fileInfo, err := file.Stat()
	if err != nil {
		log.Fatalf("file err:%s", err)
	}
	info := make([]byte, fileInfo.Size())
	file.Read(info)
	pub, err := x509.ReadPublicKeyFromPem(info)
	if err != nil {
		log.Fatalf("generate key err:%s", err)
	}

	//message wait encrypt
	privateMsg, err := pub.EncryptAsn1(msg, rand.Reader)
	return privateMsg
}

func SM2Decrypt(privateKeyPath string, msg []byte) string {
	file, err := os.Open(privateKeyPath)
	fileInfo, err := file.Stat()
	if err != nil {
		log.Fatalf("file err:%s", err)
	}
	info := make([]byte, fileInfo.Size())
	file.Read(info)
	privateKey, _ := x509.ReadPrivateKeyFromPem(info, nil)
	encryptMsg, _ := privateKey.DecryptAsn1(msg)
	return string(encryptMsg)
}

func Sm3Encrypt(data string) []byte {
	fmt.Println("data", []byte(data))
	h := sm3.New()
	h.Write([]byte(data))
	sum := h.Sum(nil)
	return sum
}

func Sha256Encrypt(data string) string {
	sha := sha256.New()
	sha.Write([]byte(data))
	sum := sha.Sum(nil)
	return hex.EncodeToString(sum)
}

func RsaSign(priKey string, msg []byte) ([]byte, error) {
	privateBlock, _ := pem.Decode([]byte(priKey))
	if privateBlock == nil {
		zap.L().Error("rsa sign private key err")
		return nil, errors.New("rsa sign private key err")
	}
	privateKey, err := cryx509.ParsePKCS1PrivateKey(privateBlock.Bytes)
	if err != nil {
		zap.L().Error("privateKey is not  *rsa.PrivateKey")
		return nil, errors.New("privateKey is not  *rsa.PrivateKey")
	}
	h := sha256.New()
	h.Write(msg)
	hashed := h.Sum(nil)
	return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
}

/**
 * @description: rsa公钥验签
 * @author: hmf
 * @date: 2023/2/7 17:07
 * @param:
 * @return:
 **/
func RsaVerify(publicKeypem string, src []byte, sign []byte) error {
	publicBlock, rest := pem.Decode([]byte(publicKeypem))
	if publicBlock == nil {
		fmt.Println(publicBlock, rest)
		panic("public key error")
	}

	pub, err := cryx509.ParsePKCS1PublicKey(publicBlock.Bytes)
	if err != nil {
		panic("publicKey is not  *rsa.PublicKey")
	}
	//publicKey := pub.(*rsa.PublicKey)
	h := crypto.SHA256.New()
	h.Write(src)
	hashed := h.Sum(nil)
	return rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed, sign)
}
